<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Apache Commons-Pool 源码分析 - 开源需要的是激情与坚持 - ITeye技术网站</title>
    <meta name="description" content="   Commons-Pool  首先看下两个重要的类结构：       ObjectPool defines  a simple pooling interface.    GenericObjectPool: ObjectPool implementation with configurable LIFO/FIFO behavior. The       default behavior is  ..." />
    <meta name="keywords" content=" Apache Commons-Pool 源码分析" />
    <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />
    <link rel="search" type="application/opensearchdescription+xml" href="/open_search.xml" title="ITeye" />
    <link href="/rss" rel="alternate" title="开源需要的是激情与坚持" type="application/rss+xml" />
    <link href="http://www.iteye.com/stylesheets/blog.css?1393920955" media="screen" rel="stylesheet" type="text/css" />
<link href="http://www.iteye.com/stylesheets/themes/blog/blue.css?1326191326" media="screen" rel="stylesheet" type="text/css" />
    <script src="http://www.iteye.com/javascripts/application.js?1358214518" type="text/javascript"></script>
    <script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-535605-1']);
  _gaq.push(['_setDomainName', 'iteye.com']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>


      <link href="http://www.iteye.com/javascripts/syntaxhighlighter/SyntaxHighlighter.css?1348819953" media="screen" rel="stylesheet" type="text/css" />
  <script src="http://www.iteye.com/javascripts/syntaxhighlighter/shCoreCommon.js?1325907333" type="text/javascript"></script>
<script src="http://www.iteye.com/javascripts/hotkey.js?1324994303" type="text/javascript"></script>
  <script src="http://www.iteye.com/javascripts/code_favorites.js?1358214518" type="text/javascript"></script>
<script src="http://www.iteye.com/javascripts/weiboshare.js?1324994303" type="text/javascript"></script>
  </head>
  <body>
    <div id="header">
      <div id="blog_site_nav">
  <a href="http://www.iteye.com/" class="homepage">首页</a>
  <a href="http://www.iteye.com/news">资讯</a>
  <a href="http://www.iteye.com/magazines">精华</a>
  <a href="http://www.iteye.com/forums">论坛</a>
  <a href="http://www.iteye.com/ask">问答</a>
  <a href="http://www.iteye.com/blogs">博客</a>
  <a href="http://www.iteye.com/blogs/subjects">专栏</a>
  <a href="http://www.iteye.com/groups">群组</a>
  <a href="#" onclick="return false;" id="msna"><u>更多</u> <small>▼</small></a>
  <div class="quick_menu" style="display:none;">
    <a target="_blank" href="http://job.iteye.com/iteye">招聘</a>
    <a href="http://www.iteye.com/search">搜索</a>
  </div>
</div>

      <div id="user_nav">
      <a href="/login" class="welcome" title="登录">您还未登录 !</a>
    <a href="/login">登录</a>
    <a href="/signup" class="nobg">注册</a>
  </div>

    </div>

    <div id="page">
      <div id="branding" class="clearfix">
        <div id="blog_name">
          <h1><a href="/">开源需要的是激情与坚持</a></h1>
        </div>
        <div id='fd'></div>
        <div id="blog_navbar">
          <ul>
            <li class='blog_navbar_for'><a href="http://pangwu86.iteye.com"><strong>博客</strong></a></li>
            <li ><a href="/weibo">微博</a></li>
            <li ><a href="/album">相册</a></li>
            <li ><a href="/link">收藏</a></li>
            <li ><a href="/blog/guest_book">留言</a></li>
            <li ><a href="/blog/profile">关于我</a></li>
          </ul>
    
          <div class="search">
            <form action="/blog/search" method="get">
              <input class="search_text" id="query" name="query" style="margin-left: 10px;width: 110px;" type="text" value="" />
              <input class="submit_search" type="submit" value="" />
            </form>
          </div> 
          <div id="fd"></div>         
        </div>
      </div>
      
      <div id="content" class="clearfix">
        <div id="main">
          



          


<div class="h-entry" style='display:none'>
  <a href="http://pangwu86.iteye.com" class="p-author" target="_blank">pangwu86</a>
</div>


<div class="blog_main">
  <div class="blog_title">
    <h3>
      <a href="/blog/1123801">Apache Commons-Pool 源码分析</a>
      <em class="actions">      </em>
    </h3>
    <ul class='blog_categories'><strong>博客分类：</strong> <li><a href="/category/164334">源码分析</a></li> </ul>
        <div class='news_tag'>&nbsp;</div>
  </div>

  <div id="blog_content" class="blog_content">
    <p> </p>
<h1><span>Commons-Pool</span></h1>
<p class="MsoNormal"><span>首先看下两个重要的类结构：</span></p>
<p class="MsoNormal"><span><img alt="" height="87" width="439" src="/upload/picture/pic/94239/36ff0440-b3f7-3397-a15c-5f0a9b75a06c.jpg"></span></p>
<p style="margin-top: 6.0pt; margin-right: 5.25pt; margin-bottom: 3.0pt; margin-left: 5.25pt; text-align: left;" class="MsoNormal"> </p>
<p style="margin-top: 6.0pt; margin-right: 5.25pt; margin-bottom: 3.0pt; margin-left: 5.25pt; text-align: left;" class="MsoNormal"><span><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/ObjectPool.html"><span>ObjectPool</span></a></span><span> defines
a simple pooling interface.</span></p>
<ul>
<li style="color: black; text-align: left;" class="MsoNormal">
<span style="color: windowtext;"><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html"><span>GenericObjectPool</span></a></span><span>: ObjectPool implementation with configurable LIFO/FIFO behavior. The
     default behavior is for the pool to act as a LIFO queue. What this means
     is that when there are idle objects available in the pool, borrowObject
     returns the most recently returned ("last in") instance. If the </span><span>lifo</span><span> the property of the pool false, instances
     are returned in the oppposite order - first-in, first-out.</span>
</li>
<li style="color: black; text-align: left;" class="MsoNormal">
<span style="color: windowtext;"><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/StackObjectPool.html"><span>StackObjectPool</span></a></span><span>: ObjectPool implementation with a LIFO (Last In First Out) behavior.</span>
</li>
<li style="color: black; text-align: left;" class="MsoNormal">
<span style="color: windowtext;"><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/SoftReferenceObjectPool.html"><span>SoftReferenceObjectPool</span></a></span><span>: ObjectPool implementation with a LIFO (Last In First Out) behavior.
     Additionally this pool wraps each object in a SoftReference allowing the
     garbage collector to remove them in response to memory demand.</span>
</li>
</ul>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span style="color: #3366ff;"><span>ObjectPool </span><span>定义了池相关操作的接口</span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;"> </span></span></p>
<p class="MsoNormal"><span style="color: #3366ff;"><span>GenericObjectPool </span><span>提供了后进先出（<span>LIFO</span>）与先进先出（<span>FIFO</span>）两种行为模式的池。默认情况是采用后进先出，即当有空闲对象时，调用<span>borrowObject</span>方法，返回最近时刻放进去的那个实例对象。这个行为是通过<span>lifo</span>这个属性控制的。</span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;"> </span></span></p>
<p class="MsoNormal"><span style="color: #3366ff;"><span>StackObjectPool </span><span>采用后进先出行为模式的池。（栈的特点，学过数据结构的都懂的）</span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;"> </span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;">SoftReferenceObjectPool </span></span><span><span style="color: #3366ff;">采用后进先出行为模式的池。池内对象被<span>SoftReference</span>包裹，允许垃圾回收器在有内存需要的时候删除这部分对象。</span></span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>除了上述信息外，如果你查看过三个实现类的源码，会发现下面这些特点：</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>GenericObjectPool </span><span>采用的是<span>org.apache.commons.collections.CursorableLinkedList</span>对象来保存对象池里的对象。而在新版本中（至少<span>1.5.6</span>已经是了），<span>CursorableLinkedList</span>这里类被拷贝到了<span>org.apache.commons.pool.impl</span>包下， 也就是说是用<span>pool</span>组件不再需要依赖<span>commons-collections</span>组件了。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>StackObjectPool </span><span>采用的是<span>java.util.Stack</span>对象来保存对象池里的对象。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>SoftReferenceObjectPool </span><span>采用的是<span>java.util.ArrayList</span>对象来保存对象池里的对象。关于这里的软引用问题，不做深入解释，大家只要明白当内存不足的时候，池中的对象可以被<span>Java</span>虚拟机回收。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>GenericObjectPool </span><span>是三个实现中最复杂的，每次调用<span>borrowObject</span>或<span>returnObject</span>，度会涉及空闲对象分配，多线程等问题。分析源码时，推荐先从<span>StackObjectPool</span>看起，最后再分析<span>GenericObjectPool</span>。</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span><img alt="" height="87" width="326" src="/upload/picture/pic/94237/88f16d5a-0493-3252-8c9f-1d7ae77c93a4.jpg"></span></p>
<p style="margin-top: 6.0pt; margin-right: 5.25pt; margin-bottom: 3.0pt; margin-left: 5.25pt; text-align: left;" class="MsoNormal"> </p>
<p style="margin-top: 6pt; margin-right: 5.25pt; margin-bottom: 3pt; margin-left: 5.25pt; text-align: left;" class="MsoNormal"><span>
</span></p>
<p style="margin-top: 6.0pt; margin-right: 5.25pt; margin-bottom: 3.0pt; margin-left: 5.25pt; text-align: left;" class="MsoNormal"><span>A </span><span><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/KeyedObjectPool.html"><span>KeyedObjectPool</span></a></span><span> pools
instances of multiple types. Each type may be accessed using an arbitrary key.</span></p>
<ul>
<li style="color: black; text-align: left;" class="MsoNormal">
<span style="color: windowtext;"><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericKeyedObjectPool.html"><span>GenericKeyedObjectPool</span></a></span><span>: ObjectPool implementation with a FIFO (First In First Out)
     behavior.</span>
</li>
<li style="color: black; text-align: left;" class="MsoNormal">
<span style="color: windowtext;"><a href="http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/StackKeyedObjectPool.html"><span>StackKeyedObjectPool</span></a></span><span>: ObjectPool implementation with a LIFO (Last In First Out) behavior.</span>
</li>
</ul>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span style="color: #3366ff;"><span>KeyedObjectPool </span><span>包含多种类型的池，采用<span>K-V</span>方式，每个类型都可以通过特定的<span>Key</span>获取。</span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;"> </span></span></p>
<p class="MsoNormal"><span style="color: #3366ff;"><span>GenericKeyedObjectPool</span><span>采用先进先出行为模式的池。</span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;"> </span></span></p>
<p class="MsoNormal"><span><span style="color: #3366ff;">StackKeyedObjectPool</span></span><span><span style="color: #3366ff;">采用后进先出行为模式的池。</span></span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>KeyedObjectPool</span><span>的实现类特点可以参照对应的<span>ObjectPool</span>实现类，基本结构是一致的。</span></p>
<p class="MsoNormal"><span> </span></p>
<p> </p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>通过上面的信息，可以看到主要的池接口就是<span>ObjectPool</span>与<span>KeyedObjectPool,</span>从他们作为入口来进行分析。</span></p>
<h1><span>ObjectPool</span></h1>
<p class="MsoNormal"><span>先看一张类图：</span></p>
<p class="MsoNormal"><img alt="" height="557" width="673" src="/upload/picture/pic/94235/f36b0125-e519-3f82-b640-5a6a096264ce.jpg"></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>从图中可以看出来：</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>GenericObjectPool</span><span>是继承了<span>BaseObjectPool</span>，<span>BaseObjectPool</span>实现了<span>ObjectPool</span>接口，因此<span>GenericObjectPool</span>是间接实现了<span>ObjectPool</span>接口。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>其中<span>ObjectPool</span>与<span>BaseObjectPool</span>中的<span>setFactory</span>方法在最新的版本<span>2.0</span>中（分析时查看的是<span>svn</span>中的源码）已经被移除<span>,</span>因为基本上在<span>new</span>一个工厂实例的时候就需要放入这个<span>factory</span>，所以这个方法被移除是正常的。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>并且发现<span>2.0</span>最大的特点就是支持泛型了，也就是说需要<span>JDK1.5</span>以上的支持。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.ObjectPool</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>接口中提供了如下方法：</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span>
</span></p>
<pre name="code" class="java">Object borrowObject() // 从池中获得一个对象
void returnObject(Object obj) // 返回一个对象给池
void invalidateObject(Object obj) // 使对象实效，不再受池管辖（必须是已经从池中获得的对象）
void addObject() // 生成一个对象（通过工程或其他实现方式），并将其放入空闲队列中
int getNumIdle() // 获得空闲对象的数量
int getNumActive() // 获得活动对象的数量
void clear() // 清空池中空闲对象，释放相关资源
void close() // 关闭池，释放所有与它相关资源
void setFactory(PoolableObjectFactory factory) // 设置池对象工厂</pre>
 
<p> </p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.BaseObjectPool</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>这个类没啥可说的，大部分方法都是简单实现或直接抛异常<span>,</span>稍微看下源码就会明白。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.impl.StackObjectPool</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>构造函数中，就是将池容器一个<span>stack</span>对象初始化，并设定最小容量（默认为<span>4</span>）。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>borrowObject</span><span>方法</span></p>
<p class="MsoNormal"><span>
</span></p>
<pre name="code" class="java">    public synchronized Object borrowObject() throws Exception {
        assertOpen();
        Object obj = null;
        boolean newlyCreated = false;
        while (null == obj) {
           //  池是否为空
            if (!_pool.empty()) {
              // 栈里有空闲对象，弹出栈中最近放进去的那个对象，即栈顶对象
                obj = _pool.pop();
            } else {
              // 池是空的，这里会先判断工厂是否为空
                if(null == _factory) {
                    throw new NoSuchElementException();
                } else {
                  // 调用工厂的生产新对象
                    obj = _factory.makeObject();
                    newlyCreated = true;
                  if (obj == null) {
                    throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null.");
                  }
                }
            }
            // 如果生产了对象，需要先激活对象（使其成为初始状态），再进行验证，验证不通过的话，需要销毁这个对象
            if (null != _factory &amp;&amp; null != obj) {
                try {
                    _factory.activateObject(obj);
                    if (!_factory.validateObject(obj)) {
                        throw new Exception("ValidateObject failed");
                    }
                } catch (Throwable t) {
                    PoolUtils.checkRethrow(t);
                    try {
                        _factory.destroyObject(obj);
                    } catch (Throwable t2) {
                        PoolUtils.checkRethrow(t2);
                        // swallowed
                    } finally {
                        obj = null;
                    }
                    if (newlyCreated) {
                        throw new NoSuchElementException(
                            "Could not create a validated object, cause: " +
                            t.getMessage());
                    }
                }
            }
        }
       // 活动对象数加一，返回对象
        _numActive++;
        return obj;
    }</pre>
 
<p> </p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>过程非常简单，先判断池是否已经关闭，然后进去借对象的循环，直到接到对象或抛出异常为止。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>returnObject</span><span>方法</span></p>
<p class="MsoNormal"><span>
</span></p>
<pre name="code" class="java"> 
public synchronized void returnObject(Object obj) throws Exception {
    // 池是否关闭了
        boolean success = !isClosed();
        if(null != _factory) {
           // 验证对象
            if(!_factory.validateObject(obj)) {
                success = false;
            } else {
                try {
                 // 验证通过的情况下，需要将这个对象设置成空闲对象的状态
                    _factory.passivateObject(obj);
                } catch(Exception e) {
                    success = false;
                }
            }
        }
       // 根据池是否关闭与验证结果，判断这个对象是否应该销毁
        boolean shouldDestroy = !success;
       // 活动对象数减一
        _numActive--;
        if (success) {
           // 如果池中空闲对象已经达到了设定的最大值，那么将池中第一个对象弹出并销毁，将刚刚传入的那个对象压入栈中
            Object toBeDestroyed = null;
            if(_pool.size() &gt;= _maxSleeping) {
                shouldDestroy = true;
                toBeDestroyed = _pool.remove(0); // remove the stalest object
            }
            _pool.push(obj);
            obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
        }
        notifyAll(); // _numActive has changed
 
       // 进行对象销毁
        if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
            try {
                _factory.destroyObject(obj);
            } catch(Exception e) {
                // ignored
            }
        }
    }
 </pre>
 
<p> </p>
<p class="MsoNormal"><span>过程依然简单，就是先验证传入的对象，验证通过，就放入池中。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>addObject</span><span>方法与<span>returnObject</span>及其类似，就是传入的那个对象，变成了通过工厂方法<span>makeObject</span>来生成，其他过程完全一致<span>,</span>这里不再分析。</span></p>
<p class="MsoNormal"><span>其他几个方法<span>invalidateObject</span>，<span>clear</span>等十分简单，也不分析了。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>总结一下，通过对<span>StackObjectPool</span>的分析，就可以使大家对池的管理有一个总体的认识。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>池对于对象的管理，主要就是分为借出，归还，验证，销毁，激活，钝化这几个功能。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>而其中的一些细节就是如何组织这几个功能，比如在借出与归还前都要进行对象的验证<span>,</span>放入池前需要钝化对象等。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.impl.SoftReferenceObjectPool</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>看过<span>StackObjectPool</span>再看<span>SoftReferenceObjectPool</span>，你会发现如此相似，甚至逻辑都一致。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>最大区别就是放入池中对象是下面这样的<span>:</span></span></p>
<p class="MsoNormal"><span> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: x-small;"><strong><span style="text-decoration: underline;">
</span></strong></span></p>
<pre name="code" class="java"><strong>new SoftReference(obj, refQueue)</strong></pre>
<p><strong>
<br></strong></p>
<p> </p>
<p style="text-align: left;" class="MsoNormal"><span>对象被软引用包装了起来，所以使得在内存不足的时候，可以让垃圾回收器强制销毁掉这部分对象，来释放内存。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>有个比较奇怪的地方就是，在分析源码的过程中，竟然没有找到这个池对象的工厂类</span><span style="font-size: 10.0pt;">...</span></p>
<p style="text-align: left;" class="MsoNormal"><span>亲爱的</span><span>SoftReferenceObjectPoolFactory</span><span>你到底是藏到哪里去了<span>…</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.impl.GenericObjectPool</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>这个类比较复杂，前三百多行都是定义的一些常量，基本上就是<span>pool</span>的默认配置信息了。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>紧接着是构造函数，你会看到<span>n</span>多构造函数，主要是参数不同。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>第一个参数必然是<span>PoolableObjectFactory</span>（几乎所有的<span>Pool</span>对象实现类都要依赖这个工厂类，后面会详细讲解）， 后面的参数是相关设置参数，你可以单独设置，或者使用一个内部类<span>PoolableObjectFactory.Config,</span>里面全是都是<span>public</span>的属性，可以直接修改。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>关于<span>PoolableObjectFactory.Config</span>的属性，采用默认配置是完全可以正常工作的，当然如果你需要更加细致的控制，你就必须了解这些属性</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span>
</span></p>
<pre name="code" class="java">public static class Config {
		// 允许最大空闲对象数
        public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
 		// 允许最小空闲对象数
        public int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
        // 允许最大活动对象数
        public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
        // 允许最大等待时间毫秒数
        public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
        // 当池中对象用完时，请求新的对象所要执行的动作
        public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
        // 是否在从池中取出对象前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
        public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
        // 是否在向池中归还对象前进行检验,如果检验失败
        public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
        // 连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
        public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
        // 在空闲连接回收器线程运行期间休眠的时间毫秒数. 如果设置为非正数,则不运行空闲连接回收器线程
        public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
        // 设定在进行后台对象清理时，每次检查对象数
        public int numTestsPerEvictionRun =  GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
        // 被空闲对象回收器回收前在池中保持空闲状态的最小时间毫秒数
        public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
        // 被空闲对象回收器回收前在池中保持空闲状态的最小时间毫秒数
        public long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
        // 是否采用后进先出策略
        public boolean lifo = GenericObjectPool.DEFAULT_LIFO;
    }
</pre>
 
<p> </p>
<p class="MsoNormal"><span>从六百行到一千行这部分，是上面修改参数的方法，其中主要涉及一个<span>allocate</span>方法，会从新分配空闲对象。</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>下面分析下这个方法：</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span>
</span></p>
<pre name="code" class="java">    private synchronized void allocate() {
        if (isClosed()) return;
 
        // First use any objects in the pool to clear the queue
        for (;;) {
            if (!_pool.isEmpty() &amp;&amp; !_allocationQueue.isEmpty()) {
                Latch latch = (Latch) _allocationQueue.removeFirst();
                latch.setPair((ObjectTimestampPair) _pool.removeFirst());
                _numInternalProcessing++;
                synchronized (latch) {
                    latch.notify();
                }
            } else {
                break;
            }
        }
 
        // Second utilise any spare capacity to create new objects
        for(;;) {
            if((!_allocationQueue.isEmpty()) &amp;&amp; (_maxActive &lt; 0 || (_numActive + _numInternalProcessing) &lt; _maxActive)) {
                Latch latch = (Latch) _allocationQueue.removeFirst();
                latch.setMayCreate(true);
                _numInternalProcessing++;
                synchronized (latch) {
                    latch.notify();
                }
            } else {
                break;
            }
        }
    }
 </pre>
 
<p> </p>
<p class="MsoNormal"><span>首先判断该池是否已经关闭</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>然后<span>…</span></span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>再然后<span>…</span></span></p>
<p class="MsoNormal"><span> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>额，暂时没有完全看懂，实在不好乱讲，以后再详细补完这部分。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;">borrowObjcet</span><span>，</span><span style="font-size: 10.0pt;">returnObject </span><span>也稍后补完。</span></p>
<p style="text-align: left;" class="MsoNormal"> </p>
<p style="text-align: left;" class="MsoNormal"> </p>
<p style="text-align: left;" class="MsoNormal"><span>下面看一下一个比较重要的类，基本上你要使用</span><span style="font-size: 10.0pt;">Pool</span><span>框架，都要与它打交道</span></p>
<p class="MsoNormal"><strong><span><span style="font-size: medium;">org.apache.commons.pool.PoolableObjectFactory</span></span></strong></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>这是一个接口类，定义了生成对象，销毁对象，验证对象，激活对象，钝化对象的方法。</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span style="font-size: x-small;">
</span></p>
<pre name="code" class="java">Object makeObject()
void destroyObject(Object obj)
boolean validateObject
void activateObject(Object obj)
void passivateObject(Object obj)</pre>
 
<p> </p>
<p style="text-align: left;" class="MsoNormal"><span>当时要使用</span><span style="font-size: 10.0pt;">Commons-Pools</span><span>时，你就需要新建一个类，实现这个接口，然后实例化你需要的工厂类（</span><span style="font-size: 10.0pt;">StackObjectPoolFactory</span><span>，</span><span style="font-size: 10.0pt;">GenericObjectPoolFactory</span><span>，根据你的需要来选择吧），然后用工厂生成你的池对象（</span><span style="font-size: 10.0pt;">Pool</span><span>）。</span></p>
<p style="text-align: left;" class="MsoNormal"> </p>
<p style="text-align: left;" class="MsoNormal"> </p>
<p style="text-align: left;" class="MsoNormal"> </p>
<h1><span>KeyedObjectPool</span></h1>
<p style="text-align: left;" class="MsoNormal"><span>同样也来看一张类图：</span></p>
<p style="text-align: left;" class="MsoNormal"><img alt="" height="582" width="749" src="/upload/picture/pic/94233/85869353-651b-3490-b6c7-85234a37be4c.jpg"></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>可以看出来</span><span style="font-size: 10.0pt;">KeyedObjectPool</span><span>类结构与</span><span style="font-size: 10.0pt;">ObjectPool</span><span>很类似，就是很多方法中多一个</span><span style="font-size: 10.0pt;">key</span><span>参数而已，如果查看源码也会发现，整个代码逻辑也基本类似，那到底</span><span style="font-size: 10.0pt;">KeyedObjectPool</span><span>是为了解决什么问题而提出来的呢？</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>就个人理解，在使用普通的池的时候，你只能通过这个池获得一种对象，如果你想获得不同的对象要怎么办呢？那就分组吧，将不同类型的对象放在不同的池中，但这样你是不是就要维护多个池呢。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>针对这个问题，</span><span style="font-size: 10.0pt;">map</span><span>的数据结构可以给你提供一个好思路，新建一个</span><span style="font-size: 10.0pt;">map</span><span>，</span><span style="font-size: 10.0pt;">key</span><span>为组名称，</span><span style="font-size: 10.0pt;">value</span><span>为对应的池。就是相当于提供一个更大的容器，来存放多个池，你只需要管理这个大容器就好了。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>举个现实中的例子，比如你去小卖部买饮料（调用</span><span style="font-size: 10.0pt;">borrowObject</span><span>）。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>这里的小卖部就是一个</span><span style="font-size: 10.0pt;">KeyedObjectPool</span><span>，可乐就相当于放在可乐池（可乐</span><span style="font-size: 10.0pt;">Pool</span><span>）中对象，雪碧是放在雪碧池（雪碧</span><span style="font-size: 10.0pt;">Pool</span><span>）中的对象，当然一般他们会放在一个冰柜中（冰柜</span><span style="font-size: 10.0pt;">Map</span><span>）。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>当你在小卖部（</span><span style="font-size: 10.0pt;">KeyedObjectPool</span><span>）买饮料时，小卖部老板会根据你的要求（你提供的</span><span style="font-size: 10.0pt;">key</span><span>，假如你要可乐），到冰柜中寻找可乐池（调用冰柜</span><span style="font-size: 10.0pt;">Map</span><span>的</span><span style="font-size: 10.0pt;">get</span><span>方法），然后从返回的池（可乐池）中拿出你要的可乐（如果是</span><span style="font-size: 10.0pt;">stack</span><span>，会调用</span><span style="font-size: 10.0pt;">pop</span><span>方法），最后交给你。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>基本思路就是这样，当然代码中会有一些差别。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>所以这部分代码，你只要看懂了</span><span style="font-size: 10.0pt;">ObjectPool</span><span>的，这里就不会有任何难度了，只是多了一个</span><span style="font-size: 10.0pt;">Map</span><span>容易而已。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;">#######################</span><span>邪恶的分割线</span><span style="font-size: 10.0pt;">#######################</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>从</span><span style="font-size: 10.0pt;">Apache</span><span>的</span><span style="font-size: 10.0pt;">SVN</span><span>中拉下的代码来看，</span><span style="font-size: 10.0pt;">trunk</span><span>中已经是</span><span style="font-size: 10.0pt;">2.0</span><span>版的代码了，除了加入泛型以外，就是修正了一些方法与参数（</span><span style="font-size: 10.0pt;">1.5.6</span><span>中已经有很多注释提示了会在</span><span style="font-size: 10.0pt;">2.0</span><span>中修正），但基本的思路没有变化，所以可以继续研究学习</span><span style="font-size: 10.0pt;">1.5.X</span><span>的代码。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>最后总结下，</span><span style="font-size: 10.0pt;">Commons-Pool</span><span>到底是为我们做了哪些？</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"><span style="color: #ff0000; font-size: medium;"> </span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>首先它定义了池管理方面的</span><span style="font-size: 10.0pt;">API</span><span>，并考虑了多线程，多种数据结构，内容不足等情况。</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"><span style="color: #ff0000; font-size: medium;"> </span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>其次它为我们提供一个同时管理多个池的解决方案。</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"><span style="color: #ff0000; font-size: medium;"> </span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>留给使用者，主要就是</span><span style="font-size: 10.0pt;">PoolableObjectFactory</span><span>与</span><span style="font-size: 10.0pt;">KeyedPoolableObjectFactory</span><span>。</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"><span style="color: #ff0000; font-size: medium;"> </span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>只要使用者将对象的生成，销毁，验证，激活与钝化做好，做到完善，没有歧义（比如什么样的状态算是激活，什么是钝化后的状态），那剩下的就可以放心的交给</span><span style="font-size: 10.0pt;">Commons-Pool</span><span>来管理你的池了。</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="color: #ff0000; font-size: medium;"><span>最好的一个例子也算是官方例子吧，就是</span><span style="font-size: 10.0pt;">Commons-DBCP</span><span>（数据库连接池），等下次来分析下</span><span style="font-size: 10.0pt;">DBCP</span><span>是怎么使用</span><span style="font-size: 10.0pt;">Pool</span><span>来管理数据库连接的。</span></span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>最后贴一段提示，告诉你到底什么时候你才会需要一个池：</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"> </p>
<p style="text-align: left;" class="MsoNormal"><a name="17"><strong><span>什么时候不要池化</span></strong></a></p>
<p style="text-align: left;" class="MsoNormal"><strong><span style="font-size: 12.0pt;"> </span></strong></p>
<p style="text-align: left;" class="MsoNormal"><span>采用对象池化的本意，是要通过减少对象生成的次数，减少花在对象初始化上面的开销，从而提高整体的性能。然而池化处理本身也要付出代价，因此，并非任何情况下都适合采用对象池化。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;">Dr. Cliff Click</span><span>在</span><span style="font-size: 10.0pt;">JavaOne 2003</span><span>上发表的《</span><span style="font-size: 10.0pt;">Performance Myths Exposed</span><span>》中，给出了一组其它条件都相同时，使用与不使用对象池化技术的实际性能的比较结果。他的实测结果表明：</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>对于类似</span><span style="font-size: 10.0pt;">Point</span><span>这样的轻量级对象，进行池化处理后，性能反而下降，因此不宜池化；</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>对于类似</span><span style="font-size: 10.0pt;">Hashtable</span><span>这样的中量级对象，进行池化处理后，性能基本不变，一般不必池化（池化会使代码变复杂，增大维护的难度）；</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>对于类似</span><span style="font-size: 10.0pt;">JPanel</span><span>这样的重量级对象，进行池化处理后，性能有所上升，可以考虑池化。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p style="text-align: left;" class="MsoNormal"><span>根据使用方法的不同，实际的情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上，不宜池化的对象的范围可能会更大。不过，对于像网络和数据库连接这类重量级的对象来说，目前还是有池化的必要。</span></p>
<p style="text-align: left;" class="MsoNormal"><span>基本上，只在重复生成某种对象的操作成为影响性能的关键因素的时候，才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话，还是不采用对象池化技术，以保持代码的简明，而使用更好的硬件和更棒的虚拟机来提高性能为佳。</span></p>
<p style="text-align: left;" class="MsoNormal"><span style="font-size: 10.0pt;"> </span></p>
<p> </p>
  </div>

  


  <IFRAME SRC="/iframe_ggbd/794" SCROLLING=no WIDTH=468 HEIGHT=60 FRAMEBORDER=0></IFRAME>
  
  <div id="bottoms" class="clearfix">
    <div id="digg_bottom" class="clearfix"><div class='digged'><strong>5</strong> <br/>顶</div><div class='digged'><strong>1</strong> <br/>踩</div></div>
    <div id="share_weibo">分享到：
      <a data-type='sina' href="javascript:;" title="分享到新浪微博"><img src="/images/sina.jpg"></a>
      <a data-type='qq' href="javascript:;" title="分享到腾讯微博"><img src="/images/tec.jpg"></a>
    </div>
  </div>

  <div class="blog_nav">
    <div class="pre_next">
      <a href="/blog/1126182" class="next" title="使用Nutz+ExtJS+JBPM4.4实现会签">使用Nutz+ExtJS+JBPM4.4实现会签</a>
      |
      <a href="/blog/1122082" class="pre" title="Apache Commons-Logging 源码分析">Apache Commons-Logging 源码分析</a>
    </div>
  </div>
  <div class="blog_bottom">
    <ul>
      <li>2011-07-13 21:36</li>
      <li>浏览 2455</li>
      <li><a href="#comments">评论(1)</a></li>
      
      
      <li>分类:<a href="http://www.iteye.com/blogs/category/opensource">开源软件</a></li>      
      <li class='last'><a href="http://www.iteye.com/wiki/blog/1123801" target="_blank" class="more">相关推荐</a></li>
    </ul>
  </div>

  <div class="blog_comment">
    <h5>评论</h5>
    <a id="comments" name="comments"></a>
    <div id="bc2211435">
  <div class="comment_title">
    1 楼
    <a href='http://lipanpally.iteye.com' target='_blank' title='lipanpally'>lipanpally</a>
    2011-08-17&nbsp;&nbsp;
    
    
  </div>
  <div class="comment_content">谢谢分享。<br /></div>
</div>


    
    
  </div>

  <div class="blog_comment">
    <h5>发表评论</h5>
            <p style="text-align:center; margin-top:30px;margin-bottom:0px;"><a href="/login" style="background-color:white;"> <img src="/images/login_icon.png" style="vertical-align:middle; margin-right: 10px;" /></a><a href="/login">  您还没有登录,请您登录后再发表评论 </a></p>
      </div>
</div>


<script type="text/javascript">
  dp.SyntaxHighlighter.HighlightAll('code', true, true);

  $$('#main .blog_content pre[name=code]').each(function(pre, index){ // blog content
    var post_id = 1123801;
    var location = window.location;
    source_url = location.protocol + "//" + location.host + location.pathname + location.search;
    pre.writeAttribute('codeable_id', post_id);
    pre.writeAttribute('codeable_type', "Blog");
    pre.writeAttribute('source_url', source_url);
    pre.writeAttribute('pre_index', index);
    pre.writeAttribute('title', 'Apache Commons-Pool 源码分析');
  });

  fix_image_size($$('div.blog_content img'), 700);

  function processComment() {
    $$('#main .blog_comment > div').each(function(comment){// comment
      var post_id = comment.id.substr(2);
      $$("#"+comment.id+" pre[name=code]").each(function(pre, index){
        var location = window.location;
        source_url = location.protocol + "//" + location.host + location.pathname + location.search;
        source_url += "#" + comment.id;
        pre.writeAttribute('codeable_id', post_id);
        pre.writeAttribute('codeable_type', "BlogComment");
        pre.writeAttribute('source_url', source_url);
        pre.writeAttribute('pre_index', index);
        pre.writeAttribute('title', 'Apache Commons-Pool 源码分析');
      });
    });
  }

  function quote_comment(id) {
    new Ajax.Request('/editor/quote', {
      parameters: {'id':id, 'type':'BlogComment'},
      onSuccess:function(response){editor.bbcode_editor.textarea.insertAfterSelection(response.responseText);
        Element.scrollTo(editor.bbcode_editor.textarea.element);}
    });
  }

  code_favorites_init();
  processComment();
  new WeiboShare({share_buttons: $('share_weibo'), img_scope: $('blog_content')});
</script>




        </div>

        <div id="local">
          <div class="local_top"></div>
          <div id="blog_owner">
  <div id="blog_owner_logo"><a href='http://pangwu86.iteye.com'><img alt="pangwu86的博客" class="logo" src="http://www.iteye.com/upload/logo/user/694760/15fa96fa-ca61-3481-8d81-0ae8bc343c40.jpg?1339516477" title="pangwu86的博客: 开源需要的是激情与坚持" /></a></div>
  <div id="blog_owner_name">pangwu86</div>
</div>

          <div id="blog_actions">
            <ul>
              <li>浏览: 45973 次</li>
              <li>性别: <img alt="Icon_minigender_1" src="http://www.iteye.com/images/icon_minigender_1.gif?1324994303" title="男" /></li>
              <li>来自: 北京</li>
              <li><img src='/images/status/offline.gif'/></li>
              
            </ul>
          </div>
          <div id="user_visits" class="clearfix">
            <h5>最近访客 <span style='font-weight:normal;font-size:12px;padding-left:30px;'><a href="/blog/user_visits">更多访客&gt;&gt;</a></span></h5>
            
              <div class="user_visit">
                <div class="logo"><a href='http://dylinshi126.iteye.com' target='_blank'><img alt="dylinshi126的博客" class="logo" src="http://www.iteye.com/images/user-logo-thumb.gif?1324994303" title="dylinshi126的博客: " /></a></div>
                <div class="left"><a href='http://dylinshi126.iteye.com' target='_blank' title='dylinshi126'>dylinshi126</a></div>
              </div>
            
              <div class="user_visit">
                <div class="logo"><a href='http://liudian3380.iteye.com' target='_blank'><img alt="liudian3380的博客" class="logo" src="http://www.iteye.com/images/user-logo-thumb.gif?1324994303" title="liudian3380的博客: " /></a></div>
                <div class="left"><a href='http://liudian3380.iteye.com' target='_blank' title='liudian3380'>liudian3380</a></div>
              </div>
            
              <div class="user_visit">
                <div class="logo"><a href='http://lys-billy.iteye.com' target='_blank'><img alt="lys_billy的博客" class="logo" src="http://www.iteye.com/images/user-logo-thumb.gif?1324994303" title="lys_billy的博客: lys_billy" /></a></div>
                <div class="left"><a href='http://lys-billy.iteye.com' target='_blank' title='lys_billy'>lys_billy</a></div>
              </div>
            
              <div class="user_visit">
                <div class="logo"><a href='http://happyDear.iteye.com' target='_blank'><img alt="happyDear的博客" class="logo" src="http://www.iteye.com/upload/logo/user/926560/13eecb80-f926-37b4-8639-c0b5d6f29046-thumb.jpg?1388376232" title="happyDear的博客: " /></a></div>
                <div class="left"><a href='http://happyDear.iteye.com' target='_blank' title='happyDear'>happyDear</a></div>
              </div>
            
          </div>

          

                      <div id="blog_menu">
              <h5>文章分类</h5>
              <ul>
                <li><a href="/">全部博客 (32)</a></li>
                
                  <li><a href="/category/107821">xml (7)</a></li>
                
                  <li><a href="/category/116703">mongoDB (2)</a></li>
                
                  <li><a href="/category/121088">数据库 (3)</a></li>
                
                  <li><a href="/category/121549">ubuntu (2)</a></li>
                
                  <li><a href="/category/125075">随便写写 (4)</a></li>
                
                  <li><a href="/category/139396">nutz (8)</a></li>
                
                  <li><a href="/category/139397">extjs (2)</a></li>
                
                  <li><a href="/category/161948">工作流 (5)</a></li>
                
                  <li><a href="/category/164334">源码分析 (4)</a></li>
                
                  <li><a href="/category/168977">技术感想 (4)</a></li>
                
                  <li><a href="/category/180512">XBlink (5)</a></li>
                
                  <li><a href="/category/183676">git (1)</a></li>
                
                  <li><a href="/category/197673">js (1)</a></li>
                
                  <li><a href="/category/197674">jquery (1)</a></li>
                
                  <li><a href="/category/221198">随便写写，杂谈 (0)</a></li>
                
              </ul>
            </div>
            <div id='month_blogs'>
              <h5>社区版块</h5>
              <ul>
                <li><a href="/blog/news">我的资讯</a> (1)</li>
                <li>
                  <a href="/blog/post">我的论坛</a> (13)
                </li>
                <li><a href="/blog/answered_problems">我的问答</a> (0)</li>
              </ul>
            </div>
            <div id="month_blogs">
              <h5>存档分类</h5>
              <ul>
                
                  <li><a href="/blog/monthblog/2012-06">2012-06</a> (1)</li>
                
                  <li><a href="/blog/monthblog/2012-05">2012-05</a> (1)</li>
                
                  <li><a href="/blog/monthblog/2011-12">2011-12</a> (1)</li>
                
                <li><a href="/blog/monthblog_more">更多存档...</a></li>
              </ul>
            </div>
            
            

            <div id="guest_books">
              <h5>最新评论</h5>
              <ul>
                
                <li>
                  <a href='http://qinboss.iteye.com' target='_blank' title='qinboss'>qinboss</a>： 
                   ...<br />
                  <a href="/blog/1107499#bc2334851">jbpm4表结构（1）</a>
                </li>
                
                <li>
                  <a href='http://han0917.iteye.com' target='_blank' title='han0917'>han0917</a>： 
                  hello,我想问下我使用XBlink序列化对象为xml的时候 ...<br />
                  <a href="/blog/1559515#bc2333935">最近的一点计划</a>
                </li>
                
                <li>
                  <a href='http://han0917.iteye.com' target='_blank' title='han0917'>han0917</a>： 
                  我想问下我使用XBlink序列化对象为xml的时候，对某字段A ...<br />
                  <a href="/blog/1188822#bc2333922">XBlink关于如何实现扩展的几点思考</a>
                </li>
                
                <li>
                  <a href='http://han0917.iteye.com' target='_blank' title='han0917'>han0917</a>： 
                  我想问下我使用XBlink序列化对象为xml的时候，对某字段A ...<br />
                  <a href="/blog/1183976#bc2333921">XBlink中关于XML/JSON格式中引用对象的路径的实现思路</a>
                </li>
                
                <li>
                  <a href='http://han0917.iteye.com' target='_blank' title='han0917'>han0917</a>： 
                  问下把对象某属性A设置为&quot;&quot;，即空串，序列 ...<br />
                  <a href="/blog/1188160#bc2333908">XBlink1.0.0版用户手册</a>
                </li>
                
              </ul>
            </div>

            <div class="local_bottom"></div>
          
        </div>
      </div>

      <div id="footer" class="clearfix">
        <div id="copyright">
          <hr/>
          声明：ITeye文章版权属于作者，受法律保护。没有作者书面许可不得转载。若作者同意转载，必须以超链接形式标明文章原始出处和作者。<br />
          &copy; 2003-2014 ITeye.com.   All rights reserved.  [ 京ICP证110151号  京公网安备110105010620 ]
        </div>
      </div>
    </div>
    <script type="text/javascript">
  document.write("<img src='http://stat.iteye.com/?url="+ encodeURIComponent(document.location.href) + "&referrer=" + encodeURIComponent(document.referrer) + "&user_id=' width='0' height='0' />");
</script>

<script src="http://csdnimg.cn/pubfooter/js/tracking.js?version=20130923164150" type="text/javascript"></script>

    
    
  </body>
</html>
